//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>
#include <PowerManager.h>
#include <nu_api.h>
#include <zenr_api.h>

PowerManager * g_pPowerManager = NULL;

extern"C" void DM_NotifyInput(int eType, int nCode, void *pParam);
void PoSetLcdChangeModePorc(TimerCallBackProc proc);
TimerCallBackProc PoGetLcdChangeModePorc();
void PoSetLcdLockScreen(Boolean Lock);
EXTERN void PoSetCpuPowerOn(Boolean PowerOn);
void PoSetLcdAutoLockTimePolicy(UInt32 byAuto);
void PoSetLcdManualLockTimePolicy (UInt32 byManualLow, UInt32 byManualHigh);

void LockScreenCallback(int eType, int nCode, void *pParam)
{//Lock notify from shellapp
    Boolean bLock = (Boolean)nCode;
    kprintf("\n=========== %s Screen ===========\n", bLock?"Lock":"Unlock");

    PoSetLcdLockScreen(bLock);//save lock screen status
    PoSetCpuPowerOn(!bLock);
    if (bLock) {
        NotifyByIsr(EVENT_INPUT, 0x80, NULL);
    }
    else {
        NotifyByIsr(EVENT_INPUT, 0x81, NULL);
    }

    return ;
}

ECode PowerManager::Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode PowerManager::Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf &buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode PowerManager::Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf &inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    //cprintf("+++++++++PowerManager::Control %d\n", nControlCode);
    //kprintf("###########################in powerManager nControlCode = %d\n", nControlCode);
    switch(nControlCode)
    {
        case 100: {/*SetLCDPolicy*/
            if (NULL == inBuffer.GetPayload()) {
                return E_INVALID_ARGUMENT;
            }
            UInt32 *p  = (UInt32 *)inBuffer.GetPayload();
            UInt32 byAuto = p[0] >> 16;
            Int32 nInterval = ((Int32 *)p)[0] & 0xFFFF;
            if (0 == byAuto) {
                PoSetLcdAutoLockTimePolicy(20);
                kprintf("----------set auto lock time by default 20s\n");
            } else {
                kprintf("----------user set auto lock time %d\n", byAuto);
                PoSetLcdAutoLockTimePolicy(byAuto);
            }
            kprintf("user set LCD Interval time is %d\n", nInterval);
            NotifyByIsr(EVENT_POWER,(int)PoEventHandler,(void *)nInterval);
            break;
        }
        case 103: {/*PoLockScreen*/
//            assert(NULL != inBuffer.GetPayload());
//            bool bLock = *(bool *)inBuffer.GetPayload();
//            kprintf("--------------------pm 103 bLock = %d\n", bLock);
            break;
        }
/*
        0: Onkey boot (default)
        1: alarm booot
        2: charger insert boot
        3: reboot
        4: unknown
 */
        case 104: {
            if (pOutBuffer == NULL || pOutBuffer->GetCapacity() < 4) {
            	return E_INVALID_ARGUMENT;
            }
            UInt32 mode = nu_GetPowerOnMode();

            switch (mode) {
                case 1: // FIH charger
                    mode = 2;
                    break;
                case 2: // FIH alarm
                    mode = 1;
                    break;
                default:
                    break;
            }
            pOutBuffer->Copy((Byte *)&mode, 4);
            break;
        }
        case 105: {/*PoReboot*/
//            assert(NULL != inBuffer.GetPayload());
//            int nInterval=*(int *)inBuffer.GetPayload();
//            setWatchDog(nInterval);
            break;
        }
        case 106: {/*PoShutdown*/
        	kprintf("-----------------------powerDown in powerManage\n");
            //nu_powerDown();
            zapi_FS->SystemShutDown();
            break;
        }
        case 108: {//set Manual lock highlight and lowlight time
            if (NULL == inBuffer.GetPayload()) {
                return E_INVALID_ARGUMENT;
            }
            UInt32 *p  = (UInt32 *)inBuffer.GetPayload();
            UInt32 byManualLow = p[0] >> 16;
        	UInt32 byManualHigh = p[0] & 0xFFFF;
        	kprintf("user set manual high time is %d, low time is %d\n", byManualHigh, byManualLow);
        	PoSetLcdManualLockTimePolicy(byManualLow, byManualHigh);
            break;
        }
        default:
            break;
    }
    return NOERROR;
}

EXTERN IDeviceDriver * CDECL CreatePowerManagers(uint_t uDeviceNo, void *pvParameter)
{
    nu_bspPm_enableSleeps(TRUE, TRUE, FALSE, FALSE);
    nu_bspIdle_Gsp_enableArmDeepSleepDecision(TRUE);
    g_pPowerManager = new PowerManager();
    AddNotify(EVENT_SLEEP,(void *)EnterSleepModeCallback);//for platform related driver use
    AddNotify(EVENT_WAKE,(void *)WakeFromSleepModeCallback);//for platform related driver use
    AddNotify(EVENT_LOCK_SCREEN,(void *)LockScreenCallback);//for noticeter use
    AddNotify(EVENT_INPUT,(void *)DM_NotifyInput);//for input event handlerg64
    TimerCallBackProc LCD_ChangeMode = PoGetLcdChangeModePorc();
    PoSetLcdChangeModePorc(LCD_ChangeMode);
    NotifyByIsr(EVENT_INPUT, 0, NULL);//simulate an input to enable keypad and lcd power management
    kprintf("Create powerManage OK!\n");
    return (IDeviceDriver *)g_pPowerManager;
}

